package mazegame;

import java.io.Serializable;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Random;
import java.util.concurrent.Semaphore;

import mazegame.Constants.Direction;

public class MazePlayer implements MazeServerInterface, Serializable {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	private int mapSize;
	private int treasureNum;
	private int nextPlayerID;
	private int playerCount;
	private int treasureCount;

	private boolean isGameJoined = false;
	private boolean isServer = false;
	private boolean isBackup = false;

	private PlayerRegistyInfo serverinfo = new PlayerRegistyInfo();
	private PlayerRegistyInfo backupinfo = new PlayerRegistyInfo();
	private PlayerRegistyInfo myInfo = new PlayerRegistyInfo();

	private boolean backupCreated = false;

	private HashMap<Integer, Integer> playerTreasureCounts;
	private HashMap<Integer, MazePosition> playerPositions;
	private HashMap<MazePosition, Integer> treasurePositions;
	private Object lock = new Object();

	private ArrayList<MazeServerInterface> playerList;
	private PlayerUI playerUI = null;
	private int myTreasureCount = 0;
	private int clientId = -1;
	private Constants.ClientStatus status = Constants.ClientStatus.CLIENT_IDLE;

	public MazeServerInterface mazeServerIntf = null;
	public MazeServerInterface mazeBackupServerIntf = null;
	public MazeServerInterface mystub = null;

	public MazePlayer() {
		playerTreasureCounts = new HashMap<Integer, Integer>();
		playerPositions = new HashMap<Integer, MazePosition>();
		treasurePositions = new HashMap<MazePosition, Integer>();
		playerList = new ArrayList<MazeServerInterface>();
	}

	public MazePlayer(PlayerUI playerUi) {
		playerTreasureCounts = new HashMap<Integer, Integer>();
		playerPositions = new HashMap<Integer, MazePosition>();
		treasurePositions = new HashMap<MazePosition, Integer>();
		playerList = new ArrayList<MazeServerInterface>();
		this.playerUI = playerUi;
	}

	@Override
	public synchronized int joinGameRemote(MazeServerInterface playerStub)
			throws RemoteException {

		System.out.println("[SERVER] join game called");

		if (playerUI.gameStatus == Constants.ServerStatus.SERVER_STOP
				|| playerUI.gameStatus == Constants.ServerStatus.SERVER_GAME_RUNNING) {
			return -1;
		} else if (playerUI.gameStatus == Constants.ServerStatus.SERVER_IDLE
				|| playerUI.gameStatus == Constants.ServerStatus.SERVER_GAME_STARTING) {
			int newId = nextPlayerID++;
			MazePosition position = new MazePosition(0, 0);
			Random random = new Random();

			// if this the first player, generate treasure positions
			if (newId == 1) {
				for (int i = 0; i < treasureNum; ++i) {
					int x = random.nextInt(mapSize);
					int y = random.nextInt(mapSize);

					if (treasurePositions.containsKey(new MazePosition(x, y))) {
						treasurePositions
								.put(new MazePosition(x, y), treasurePositions
										.get(new MazePosition(x, y)) + 1);
					} else {
						treasurePositions.put(new MazePosition(x, y), 1);
					}
				}
			}

			// generate new position for the player
			do {
				position.x = random.nextInt(mapSize);
				position.y = random.nextInt(mapSize);
			} while (playerPositions.containsValue(position)
					|| treasurePositions.containsKey(position));

			// update variables
			playerCount++;
			playerTreasureCounts.put(newId, 0);
			playerPositions.put(newId, position);

			if (playerStub != null) {

				if (newId == 2)// 2nd player who joins the game will be first
								// backup server
				{
					playerStub.bindAsBackupServer();
					PlayerRegistyInfo info = playerStub.getPlayerInfoRemote();
					mazeBackupServerIntf = initiateRemoteMazeBackupServer(
							info.host, info.port);
					backupCreated = true;
					backupinfo.host = info.host;
					backupinfo.port = info.port;

				}

				playerStub.setServerDetails(serverinfo.host, serverinfo.port,
						backupinfo.host,
						backupinfo.port);
				playerList.add(playerStub);
				System.out.println("[SERVER] player added :  playerList size "
						+ playerList.size());

			}

			// if first player, start the timer and update server
			// status
			if (newId == 1) {
				playerUI.startTimer = new GameStartTimer(this.playerUI);
				playerUI.gameStatus = Constants.ServerStatus.SERVER_GAME_STARTING;
				System.out.println("[SERVER] start game timer started");
				System.out.println("[SERVER] game status:"
						+ playerUI.gameStatus);

			}

			System.out.println("[SERVER] new client created with id:" + newId);
			return newId;
		} else {
			return -1;
		}

	}

	@Override
	public synchronized GameState moveRemote(int id,
			Constants.Direction direction) throws RemoteException {
		if(direction!=null)
		{
			System.out.println("[SERVER] : Move called with client id " + id
					+ "  direction " + direction);
			playerUI.setLogs("Move called with client id "
					+ (char) (id + (int) 'A') + "  direction " + direction);

		}
		
		GameState gameState = new GameState();

		try {


			// location of current player
			MazePosition pos = playerPositions.get(id);

			if (direction != null && pos != null) {
				// player move out of map boundary
				if ((direction == Direction.DIR_UP && pos.x - 1 >= 0)
						|| (direction == Direction.DIR_DOWN && pos.x + 1 < mapSize)
						|| (direction == Direction.DIR_LEFT && pos.y - 1 >= 0)
						|| (direction == Direction.DIR_RIGHT && pos.y + 1 < mapSize)) {
					// check for player location conflict
					if ((direction == Direction.DIR_UP && !playerPositions
							.containsValue(new MazePosition(pos.x - 1, pos.y)))
							|| (direction == Direction.DIR_DOWN && !playerPositions
									.containsValue(new MazePosition(pos.x + 1,
											pos.y)))
							|| (direction == Direction.DIR_LEFT && !playerPositions
									.containsValue(new MazePosition(pos.x,
											pos.y - 1)))
							|| (direction == Direction.DIR_RIGHT && !playerPositions
									.containsValue(new MazePosition(pos.x,
											pos.y + 1)))) {
						// move is legal

						playerUI.setLogs("Client move legal");

						// generate new player location
						MazePosition newPos = new MazePosition(pos.x, pos.y);
						if (direction == Direction.DIR_UP)
							newPos.x -= 1;
						else if (direction == Direction.DIR_DOWN)
							newPos.x += 1;
						else if (direction == Direction.DIR_LEFT)
							newPos.y -= 1;
						else
							newPos.y += 1;

						synchronized (lock)
						{
							// remove old player location and insert new player
							// location
							playerPositions.remove(pos);
							playerPositions.put(id, newPos);
							System.out.println("[SERVER] player new position x "
									+ newPos.x + " y " + newPos.y);
	
							// player
							// and update treasure map
							if (treasurePositions.containsKey(newPos)) {
								playerTreasureCounts.put(id,
										playerTreasureCounts.get(id)
												+ treasurePositions.get(newPos));
								treasurePositions.remove(newPos);
							}
						}
					} else {
						playerUI.setLogs("[ERROR] client move ilegal");
					}
				} else {
					playerUI.setLogs("[ERROR] client move ilegal");
				}

			}


			gameState.setPlayerPositions(playerPositions);
			gameState.setPlayerTreasureCounts(playerTreasureCounts);
			gameState.setTreasurePositions(treasurePositions);
			gameState.setGameStartTickcount(playerUI.gameStartTickcount);
			gameState.setServerHost(serverinfo.host);
			gameState.setServerPort(serverinfo.port);
			gameState.setBackupHost(backupinfo.host);
			gameState.setBackupPort(backupinfo.port);

			if (mazeBackupServerIntf != null) {
				mazeBackupServerIntf.setGameStateRemote(gameState);
			}

		} catch (Exception e) {
			e.printStackTrace();
		}

		return gameState;

	}

	public int getMapSizeRemote() throws RemoteException {
		return mapSize;
	}

	public void setMapSize(int mapSize) {
		this.mapSize = mapSize;
	}

	public int getTreasureNum() {
		return treasureNum;
	}

	public void setTreasureNum(int treasureNum) {
		this.treasureNum = treasureNum;
	}

	public int getNextPlayerID() {
		return nextPlayerID;
	}

	public void setNextPlayerID(int nextPlayerID) {
		this.nextPlayerID = nextPlayerID;
	}

	public int getPlayerCount() {
		return playerCount;
	}

	public void setPlayerCount(int playerCount) {
		this.playerCount = playerCount;
	}

	public int getTreasureCount() {
		return treasureCount;
	}

	public void setTreasureCount(int treasureCount) {
		this.treasureCount = treasureCount;
	}

	public HashMap<Integer, Integer> getPlayerTreasureCounts() {
		return playerTreasureCounts;
	}

	public void setPlayerTreasureCounts(
			HashMap<Integer, Integer> playerTreasureCounts) {
		this.playerTreasureCounts = playerTreasureCounts;
	}

	public HashMap<Integer, MazePosition> getPlayerPositions() {
		return playerPositions;
	}

	public void setPlayerPositions(
			HashMap<Integer, MazePosition> playerPositions) {
		this.playerPositions = playerPositions;
	}

	public HashMap<MazePosition, Integer> getTreasurePositions() {
		return treasurePositions;
	}

	public void setTreasurePositions(
			HashMap<MazePosition, Integer> treasurePositions) {
		this.treasurePositions = treasurePositions;
	}

	public boolean isGameJoined() {
		return isGameJoined;
	}

	public void setGameJoined(boolean isGameJoined) {
		this.isGameJoined = isGameJoined;
	}

	public boolean isServer() {
		return isServer;
	}

	public void setServer(boolean isServer) {
		this.isServer = isServer;
	}

	public boolean isBackup() {
		return isBackup;
	}

	public void setBackup(boolean isBackup) {
		this.isBackup = isBackup;
	}

	public int getMyTreasureCount() {
		return myTreasureCount;
	}

	public void setMyTreasureCount(int myTreasureCount) {
		this.myTreasureCount = myTreasureCount;
	}

	public Constants.ClientStatus getStatus() {
		return status;
	}

	public void setStatus(Constants.ClientStatus status) {
		this.status = status;
	}

	public int getClientId() {
		return clientId;
	}

	public void setClientId(int clientId) {
		this.clientId = clientId;
	}

	public PlayerRegistyInfo getServerInfo() {
		return serverinfo;
	}

	public void setServerInfo(PlayerRegistyInfo server) {
		this.serverinfo = server;
	}

	public PlayerRegistyInfo getBackupInfo() {
		return backupinfo;
	}

	public void setBackupInfo(PlayerRegistyInfo backupServer) {
		this.backupinfo = backupServer;
	}

	public PlayerRegistyInfo getMyInfo() {
		return myInfo;
	}

	public void setMyinfo(PlayerRegistyInfo my) {
		this.myInfo = my;
	}

	public MazeServerInterface initiateRemoteMazeServer(String host, int port) {
		try {
			Registry registry = LocateRegistry.getRegistry(host, port);
			MazeServerInterface mazeServerIntf = (MazeServerInterface) registry
					.lookup("MazeServerImpl");
			return mazeServerIntf;

		} catch (Exception e1) {
			e1.printStackTrace();
			return null;
		}
	}

	public MazeServerInterface initiateRemoteMazeBackupServer(String host,int port) {
		try {

			Registry registry = LocateRegistry.getRegistry(host, port);
			MazeServerInterface mazeBackupServerIntf = (MazeServerInterface) registry
					.lookup("MazeBackupServerImpl");
			return mazeBackupServerIntf;

		} catch (Exception e1) {
			e1.printStackTrace();
			return null;
		}
	}

	public String updateJoiningClient() {
		try {
			if (isServer) {
				this.setClientId(mazeServerIntf.joinGameRemote(null));
				playerList.add(mystub);
			} else {
				mystub = (MazeServerInterface) UnicastRemoteObject
						.exportObject(this, 0);
				this.setClientId(mazeServerIntf.joinGameRemote(mystub));
			}

			this.mapSize = mazeServerIntf.getMapSizeRemote();

			if (this.getClientId() != -1) {
				// Update Client Status
				this.setStatus(Constants.ClientStatus.CLIENT_GAME_STARTING);
				this.setGameJoined(true);
				return "Player join game successful. Joined player id is : "
						+(char)(this.getClientId() + (int)'A');
			} else {
				return "[ERROR] Player join game failed.";
			}
		} catch (RemoteException e1) {
			e1.printStackTrace();
			return " [ERROR] Player join game failed.";
		}
	}

	public String playerMoveStatus(Direction dir) {
		GameState gameState = null;
		String returnStatus = null;

		if (status == Constants.ClientStatus.CLIENT_GAME_STARTING) {

			try {
				gameState = mazeServerIntf.moveRemote(clientId, null);
				if (gameState == null) {
					System.out
							.print("Player request move failed. Game State is null");
					return "Player request move failed. Game State is null";

				}
				if (gameState.getGameStartTickcount() <= 0) {
					status = Constants.ClientStatus.CLIENT_GAME_RUNNING;
					playerTreasureCounts = gameState.getPlayerTreasureCounts();
					playerPositions = gameState.getPlayerPositions();
					treasurePositions = gameState.getTreasurePositions();
					returnStatus = "Player moved request handled successfully";
					System.out.println("Player is running..");
					returnStatus = "Player is running..";
				} else {
					returnStatus = "Maze game starting.... "
							+ gameState.getGameStartTickcount();
				}

			} catch (RemoteException e1) {
				e1.printStackTrace();
				return "[ERROR] Player request move failed.";
			} catch (Exception e2) {
				e2.printStackTrace();
				return "[ERROR] Player request move failed.";
			}

		} else if (status == Constants.ClientStatus.CLIENT_GAME_RUNNING) {

			// invoke the RMI call
			try {
				gameState = mazeServerIntf.moveRemote(clientId, dir);
				if (gameState == null) {
					System.out
							.print("Player request move failed. Game State is null");
					return "Player request move failed. Game State is null";
				} else {
					playerTreasureCounts = gameState.getPlayerTreasureCounts();
					playerPositions = gameState.getPlayerPositions();
					treasurePositions = gameState.getTreasurePositions();
					int newBackupPort = gameState.getBackupPort();
					String newBackupHost = gameState.getBackupHost();
					if (!newBackupHost.equals(backupinfo.host)
							|| newBackupPort != backupinfo.port) {
						mazeBackupServerIntf = initiateRemoteMazeBackupServer(
								gameState.getBackupHost(),
								gameState.getBackupPort());
					}

					returnStatus = "Player moved request handled successfully";
				}
			} catch (RemoteException e1) {
				System.out.println(" [ERROR] " + e1.getMessage());
				String returnstatus = "";
				if (mazeBackupServerIntf == null) {
					mazeBackupServerIntf = initiateRemoteMazeBackupServer(
							backupinfo.host, backupinfo.port);
				}
				try {

					gameState = mazeBackupServerIntf.moveRemote(clientId, null);

					mazeServerIntf = initiateRemoteMazeServer(
							gameState.getServerHost(),
							gameState.getServerPort());

					gameState = mazeServerIntf.moveRemote(clientId, dir);
					playerTreasureCounts = gameState.getPlayerTreasureCounts();
					playerPositions = gameState.getPlayerPositions();
					treasurePositions = gameState.getTreasurePositions();

					returnStatus = "Player request move successfull";

				} catch (RemoteException e) {
					e.printStackTrace();
					returnStatus = "[ERROR] Player request move failed.";
				}

				return returnStatus;
			}

		}
		return returnStatus;
	}

	public String updateMazeMap() {
		String mazeMap = "";
		String playerInfo = "Other Players \n";
		for (int i = 0; i < mapSize; ++i) {
			for (int j = 0; j < mapSize; ++j) {
				if (playerPositions.containsValue(new MazePosition(i, j))) {
					int curId = MazeUtil.getKeyByValue(playerPositions,
							new MazePosition(i, j));
					int treasure = playerTreasureCounts.get(curId);

					if (curId == clientId) {
						mazeMap = mazeMap + "*" + "\b \b";
						myTreasureCount = playerTreasureCounts.get(clientId);
					} else {
						mazeMap = mazeMap + (char) (curId + (int) 'A')
								+ "\b \b";
						playerInfo = playerInfo + "Player "
								+ (char) (curId + (int) 'A') + " owns "
								+ treasure + "\n";
					}
				} else if (treasurePositions
						.containsKey(new MazePosition(i, j)))
					mazeMap = mazeMap
							+ treasurePositions.get(new MazePosition(i, j))
									.toString() + "\b \b";
				else
					mazeMap += "0\b \b";
			}

			mazeMap += "\n";
		}

		return mazeMap + "\n My Status \n Id : "
				+ (char) (clientId + (int) 'A') + "\b \b Treasure Count : "
				+ myTreasureCount + "\n \n" + playerInfo;
	}

	@Override
	public void bindAsServer() throws RemoteException {
		String name = "MazeServerImpl";
		try {

			Registry registry = LocateRegistry.createRegistry(myInfo.port);
			registry.rebind(name, mystub);

			serverinfo.host = myInfo.host;
			serverinfo.port = myInfo.port;
			isServer = true;
			isBackup = false;
			backupCreated = true;
			System.out.println("I'm the New Server.. !!");			
			playerUI.setLogs("I'm the New Server..!!");			

			SyncServerAndBackupTimer timer = new SyncServerAndBackupTimer(this);// start sync with backup

		} catch (RemoteException e) {
			e.printStackTrace();
			throw e;
		}

	}

	@Override
	public void bindAsBackupServer() throws RemoteException {
		String name = "MazeBackupServerImpl";
		try {

			Registry registry = LocateRegistry.createRegistry(myInfo.port);
			registry.rebind(name, mystub);

			backupinfo.host = myInfo.host;
			backupinfo.port = myInfo.port;
			isServer = false;
			isBackup = true;
			System.out.println("I'm the New Backup Server.. !!");			
			playerUI.setLogs("I'm the New Backup Server..!!");				

			SyncServerAndBackupTimer timer = new SyncServerAndBackupTimer(this); // start sync with server
		} catch (RemoteException e) {
			e.printStackTrace();
			throw e;
		}

	}

	public void syncServerAndBackup() throws Exception {
		if (isServer) {
			if (backupCreated) {
				if (mazeBackupServerIntf == null) {

					mazeBackupServerIntf = initiateRemoteMazeBackupServer(
							backupinfo.host, backupinfo.port);
				}
				try {
					mazeBackupServerIntf.setGameStateRemote(this
							.getGameStateLocal());
					mazeBackupServerIntf.setPlayerListRemote(playerList);

				} catch (RemoteException e) {
					e.printStackTrace();
					playerUI.setLogs("Backup crashed...");
					MazeServerInterface newBackupServer = selectNextServer();
					if(newBackupServer != null){
					newBackupServer.bindAsBackupServer();
					newBackupServer
							.setGameStateRemote(this.getGameStateLocal());
					newBackupServer.setPlayerListRemote(playerList);
					PlayerRegistyInfo newServerInfo = newBackupServer
							.getPlayerInfoRemote();
					backupinfo.host = newServerInfo.host;
					backupinfo.port = newServerInfo.port;
					newBackupServer.setServerDetails(serverinfo.host,
							serverinfo.port,
							backupinfo.host, backupinfo.port);
					notifyClientsOnServerChange();
					mazeBackupServerIntf = initiateRemoteMazeBackupServer(
							newServerInfo.host, newServerInfo.port);
					System.out.println("Backup created.");
					System.out.println("Backup host : "+backupinfo.host);
					System.out.println("Backup port : "+backupinfo.port);
					playerUI.setLogs("New Backup created.");
					playerUI.setLogs("Backup host : "+backupinfo.host);
					playerUI.setLogs("Backup port : "+backupinfo.port);
					}else{
						throw e;
					}
				}
			}
		}

		if (isBackup) {
			GameState state = null;
			if (mazeServerIntf == null) {
				mazeServerIntf = initiateRemoteMazeServer(serverinfo.host,
						serverinfo.port);
			}
			try {
				state = mazeServerIntf.getGameStateRemote();
				this.setGameStateLocal(state);
				playerList = mazeServerIntf.getPlayerListRemote();
			} catch (RemoteException e) {
				e.printStackTrace();
				playerUI.setLogs("Server crashed...");
				MazeServerInterface newServer = selectNextServer();
				if(newServer != null){			
				newServer.bindAsServer();
				newServer.setGameStateRemote(this.getGameStateLocal());
				newServer.setPlayerListRemote(playerList);
				PlayerRegistyInfo newServerInfo = newServer
						.getPlayerInfoRemote();
				serverinfo.host = newServerInfo.host;
				serverinfo.port = newServerInfo.port;
				newServer.setServerDetails(serverinfo.host, serverinfo.port, backupinfo.host,
						backupinfo.port);
				notifyClientsOnServerChange();
				mazeServerIntf = initiateRemoteMazeServer(newServerInfo.host,
						newServerInfo.port);
				System.out.println("Server created.");
				System.out.println("Server host : "+serverinfo.host);
				System.out.println("Server port : "+serverinfo.port);
				playerUI.setLogs("New Server created.");
				playerUI.setLogs("Server host : "+serverinfo.host);
				playerUI.setLogs("Server port : "+serverinfo.port);	
				}else{
					throw e;
				}				
			}
		}
	}

	@Override
	public GameState getGameStateRemote() throws RemoteException {
		GameState gameState = new GameState();

		synchronized (lock) {
			gameState.setPlayerPositions(playerPositions);
			gameState.setPlayerTreasureCounts(playerTreasureCounts);
			gameState.setTreasurePositions(treasurePositions);
			gameState.setServerHost(serverinfo.host);
			gameState.setServerPort(serverinfo.port);
			gameState.setBackupHost(backupinfo.host);
			gameState.setBackupPort(backupinfo.port);

		}

		return gameState;
	}

	@Override
	public void setGameStateRemote(GameState gameState) throws RemoteException {

		synchronized (lock) {
			playerPositions = gameState.getPlayerPositions();
			playerTreasureCounts = gameState.getPlayerTreasureCounts();
			treasurePositions = gameState.getTreasurePositions();
			serverinfo.host = gameState.getServerHost();
			serverinfo.port = gameState.getServerPort();
			backupinfo.host = gameState.getBackupHost();
			backupinfo.port = gameState.getBackupPort();

		}

	}

	@Override
	public void setServerDetails(String serverHost, int serverPort,String backupHost, int backupPort) throws RemoteException {
		
		if(this.getServerInfo().host != serverHost || this.getServerInfo().port != serverPort)
		{
			mazeServerIntf=initiateRemoteMazeServer(serverHost, serverPort);
		}
		if(this.getBackupInfo().host != serverHost || this.getBackupInfo().port != serverPort)
		{
			mazeBackupServerIntf=initiateRemoteMazeBackupServer(backupHost, backupPort);
		}
		this.getServerInfo().host = serverHost;
		this.getServerInfo().port = serverPort;
		this.getBackupInfo().host = backupHost;
		this.getBackupInfo().port = backupPort;
		

	}

	@Override
	public PlayerRegistyInfo getPlayerInfoRemote() throws RemoteException {
		PlayerRegistyInfo info = this.getMyInfo();
		info.isBackup = this.isBackup;
		info.isServer = this.isServer;
		return info;
	}

	@Override
	public ArrayList<MazeServerInterface> getPlayerListRemote()
			throws RemoteException {
		return this.playerList;
	}

	@Override
	public void setPlayerListRemote(ArrayList<MazeServerInterface> playerList)
			throws RemoteException {
		this.playerList = playerList;
	}

	private MazeServerInterface selectNextServer() {
		MazeServerInterface server = null;
		removeCrashedPlayers();
		System.out.println("playerList.size() :" + playerList.size());
		for (int i = 0; i < playerList.size(); i++) {
			MazeServerInterface player = playerList.get(i);
			try {
				PlayerRegistyInfo playerInfor = player.getPlayerInfoRemote();
				if (playerInfor.isBackup || playerInfor.isServer) {
					continue;
				} else {
					server = player;
					break;
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}

		return server;
	}

	private void removeCrashedPlayers() {
		System.out.println(" Crash : playerList.size() :" + playerList.size());
		for (int i = 0; i < playerList.size(); i++) {
			MazeServerInterface player = playerList.get(i);
			try {

				player.getPlayerInfoRemote();

			} catch (Exception e) {
				playerList.remove(i);

			}
		}

	}

	private GameState getGameStateLocal() {
		GameState gameState = new GameState();
		gameState.setPlayerPositions(playerPositions);
		gameState.setPlayerTreasureCounts(playerTreasureCounts);
		gameState.setTreasurePositions(treasurePositions);
		gameState.setServerHost(serverinfo.host);
		gameState.setServerPort(serverinfo.port);
		gameState.setBackupHost(backupinfo.host);
		gameState.setBackupPort(backupinfo.port);
		return gameState;
	}

	private void setGameStateLocal(GameState gameState) {

		playerPositions = gameState.getPlayerPositions();
		playerTreasureCounts = gameState.getPlayerTreasureCounts();
		treasurePositions = gameState.getTreasurePositions();
		serverinfo.host = gameState.getServerHost();
		serverinfo.port = gameState.getServerPort();
		backupinfo.host = gameState.getBackupHost();
		backupinfo.port = gameState.getBackupPort();

	}
	
	private void notifyClientsOnServerChange() throws RemoteException
	{
		for(MazeServerInterface player:playerList)
		{
			PlayerRegistyInfo playerInfor = player.getPlayerInfoRemote();
			if (!playerInfor.isBackup && !playerInfor.isServer) {
				player.setServerDetails(serverinfo.host, serverinfo.port, backupinfo.host, backupinfo.port);
			}
		}
	}

}
